package org.android.data;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * Sqlite工具类
 * @author asu
 *
 */
public class XDBHelper {

	private SQLiteDatabase mDb;     
	
	static class DBOpenHelper extends SQLiteOpenHelper {

		public DBOpenHelper(Context context) {
			super(context, "tamll", null, 1);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			String sql = "CREATE TABLE cart(id INTEGER PRIMARY KEY AUTOINCREMENT,title VARCHAR(20),num VARCHAR(20))";
			db.execSQL(sql);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			String sql = "ALTER TABLE cart ADD(id INTEGER PRIMARY KEY AUTOINCREMENT,title VARCHAR(20),num VARCHAR(20))";
			db.execSQL(sql);
		}

	}
	
	
	// 单例模式
	private static XDBHelper instance = null;
	private XDBHelper(Context context) {
		DBOpenHelper dbOpenHelper = new DBOpenHelper(context);
		mDb = dbOpenHelper.getWritableDatabase();
	}
	public static XDBHelper getInstance(Context context) {
		if (instance == null) {
			instance = new XDBHelper(context);
		}
		return instance;
	}

	  /**
     * 插入数据 参数
     * @param tableName 表名
     * @param initialValues 要插入的列对应值
     * @return
     */
    public long insert(String tableName, ContentValues initialValues) {
        return mDb.insert(tableName, null, initialValues);
    }
    /**
     * 删除数据
     * @param tableName 表名
     * @param deleteCondition 条件
     * @param deleteArgs 条件对应的值（如果deleteCondition中有“？”号，将用此数组中的值替换，一一对应）
     * @return
     */
    public boolean delete(String tableName, String deleteCondition, String[] deleteArgs) {
        return mDb.delete(tableName, deleteCondition, deleteArgs) > 0;
    }
    /**
     * 更新数据
     * @param tableName 表名
     * @param initialValues 要更新的列
     * @param selection 更新的条件
     * @param selectArgs 更新条件中的“？”对应的值
     * @return
     */
    public boolean update(String tableName, ContentValues initialValues, String selection, String[] selectArgs) {
        return mDb.update(tableName, initialValues, selection, selectArgs) > 0;
    }
    /**
     * 取得一个列表
     * @param distinct 是否去重复
     * @param tableName 表名
     * @param columns 要返回的列
     * @param selection 条件
     * @param selectionArgs 条件中“？”的参数值
     * @param groupBy 分组
     * @param having 分组过滤条件
     * @param orderBy 排序
     * @return
     */
    public Cursor findList(boolean distinct, String tableName, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) {
        return mDb.query(distinct, tableName, columns, selection, selectionArgs, groupBy, having, orderBy, limit);
    }
    /**
     * 取得单行记录
     * @param tableName 表名
     * @param columns 获取的列数组
     * @param selection 条件
     * @param selectionArgs 条件中“？”对应的值
     * @param groupBy 分组
     * @param having 分组条件
     * @param orderBy 排序
     * @param limit 数据区间
     * @param distinct 是否去重复
     * @return
     * @throws SQLException
     */
    public Cursor findOne(boolean distinct, String tableName, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) throws SQLException {
        Cursor mCursor = findList(distinct, tableName, columns, selection, selectionArgs, groupBy, having, orderBy, limit);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;
    }
    /**
     * 执行SQL(带参数)
     * @param sql
     * @param args SQL中“？”参数值
     */
    public void execSQL(String sql, Object[] args) {
        mDb.execSQL(sql, args);
    }
    /**
     * 执行SQL
     * @param sql
     */
    public void execSQL(String sql) {
        mDb.execSQL(sql);
    }
    /**
     * 判断某张表是否存在
     * @param tabName 表名
     * @return
     */
    public boolean isTableExist(String tableName) {
        boolean result = false;
        if (tableName == null) {
            return false;
        }
        try {
            Cursor cursor = null;
            String sql = "select count(1) as c from sqlite_master where type ='table' and name ='" + tableName.trim() + "'";
            cursor = mDb.rawQuery(sql, null);
            if (cursor.moveToNext()) {
                int count = cursor.getInt(0);
                if (count > 0) {
                    result = true;
                }
            }
            cursor.close();
        }
        catch (Exception e) {
        }
        return result;
    }
    /**
     * 判断某张表中是否存在某字段(注，该方法无法判断表是否存在，因此应与isTableExist一起应用)
     * @param tabName 表名
     * @param columnName 列名
     * @return
     */
    public boolean isColumnExist(String tableName, String columnName) {
        boolean result = false;
        if (tableName == null) {
            return false;
        }
        try {
            Cursor cursor = null;
            String sql = "select count(1) as c from sqlite_master where type ='table' and name ='" + tableName.trim() + "' and sql like '%" + columnName.trim() + "%'";
            cursor = mDb.rawQuery(sql, null);
            if (cursor.moveToNext()) {
                int count = cursor.getInt(0);
                if (count > 0) {
                    result = true;
                }
            }
            cursor.close();
        }
        catch (Exception e) {
        }
        return result;
    }
    

	/**
	 * 封装查询到的数据到bean里面
	 * @param sql sql语句
	 * @param selectionArgs sql语句中若有参数 则填写 ，若没有 ，就不用写
	 * @param BeanClass 存放数据的Bean的Class
	 * @return
	 * @throws Exception
	 */
	public <T> List<T> selectForBeanList(Class<T> BeanClass,String sql,String... selectionArgs){
		List<T> list=null;
		try {
			//健壮性 
			if(sql==null){
				throw new Exception("sql语句为 null");
			}
			if(BeanClass==null){
				throw new Exception("BeanClass为 null");
			}
			//标记  isFind
			boolean isFinded=false;
						
			//拼凑把sql中参数填满
			sql=XSqliteUtils.setParamsToSql(sql, selectionArgs);
			T t=null;
			//获取bean的所有字段
			list=new LinkedList<T>();
			Cursor cursor=mDb.rawQuery(sql, null);
			
			while(cursor.moveToNext()){
				isFinded=true;//找到数据
				t=XSqliteUtils.parseCursorToBean(cursor, BeanClass);
				list.add(t);
			}
			cursor.close();
		} catch (Exception e) {
		}
		
		return list;
	}
/**
 * 查询一条数据到Bean里 如果没有找到 返回null
 * @param BeanClass
 * @param sql
 * @param selectionArgs
 * @return
 * @throws Exception
 */
	public <T> T selectForBean(Class<T> BeanClass,String sql,String... selectionArgs) throws Exception{
		//健壮性
		if(sql==null){
			throw new Exception("sql语句为 null");
		}
		if(BeanClass==null){
			throw new Exception("BeanClass为 null");
		}
		
		//设置标记  判断是否有查到数据
		boolean isFinded=false;
		//声明变量
		T t=null;
		
//		//拼凑把sql中参数填满
//		sql=XSqliteUtils.setParamsToSql(sql, selectionArgs);
		
//		System.out.println(selectionArgs.length);
		//把[] 变成 null
		if(selectionArgs.length==0){
			selectionArgs=null;
		}
		Cursor cursor=mDb.rawQuery(sql, selectionArgs);
		
		if(cursor.moveToNext()){
			isFinded=true;//表示找到数据
			t=XSqliteUtils.parseCursorToBean(cursor, BeanClass);
			System.out.println(t);
			
		}
		//释放资源
		cursor.close();
		
		if(isFinded){
			return t;
		}else{
			return null;
		}
	}

	/**
	 * 把map 里面描述的数据插到 table表中
	 * @param tableName 表名
	 * @param keyValues 要插入的数据的描述
	 * @return 成功则返回true 否则返回 false
	 */
	public boolean add(String tableName,Map<String,Object> keyValues){
		try {
					
			ContentValues values=new ContentValues();
			Set<Map.Entry<String, Object>> entries=keyValues.entrySet();
			for(Map.Entry<String, Object> entry:entries){
				putEntryToContentValues(entry,values);
			}
			long rowId=this.mDb.insert(tableName,null, values);
			
			if(rowId!=-1){
				return true;
			}
		} catch (Exception e) {
			Log.e("Exception", ""+e);
		}
		
		return false;
	}
	//for add
	private void putEntryToContentValues(Map.Entry<String, Object> entry,ContentValues values){
		if(entry.getValue() instanceof String){
			values.put(entry.getKey(), entry.getValue().toString());
		}
		if(entry.getValue() instanceof Integer){
			values.put(entry.getKey(), Integer.parseInt(entry.getValue().toString()));
		}
		if(entry.getValue() instanceof Float){
			values.put(entry.getKey(), Float.parseFloat(entry.getValue().toString()));
		}
		if(entry.getValue() instanceof Boolean){
			values.put(entry.getKey(), Boolean.parseBoolean((entry.getValue().toString())));
		}
		if(entry.getValue() instanceof Double){
			values.put(entry.getKey(), Double.parseDouble((entry.getValue().toString())));
		}
		if(entry.getValue() instanceof Byte){
			values.put(entry.getKey(), Byte.parseByte((entry.getValue().toString())));
		}
		if(entry.getValue() instanceof Long){
			values.put(entry.getKey(), Long.parseLong((entry.getValue().toString())));
		}
		if(entry.getValue() instanceof Short){
			values.put(entry.getKey(), Short.parseShort((entry.getValue().toString())));
		}
	}
	/**
	 * 将一个bean对象直接插到数据库里面
	 * @param tableName 表名
	 * @param bean 要插入的bean对象
	 * @return 如果成功则返回true 失败则返回false
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 */
	public <T> boolean add(String tableName,Object bean) {
		Map<String, Object> map=null;
		try {
			Method[] methods= bean.getClass().getMethods();
			map=new HashMap<String, Object>();
			//把带有get名称的方法 的名字放到notNullGetMethodName 这个数组里面来
			String[] notNullGetMethodNames=new String[methods.length];
			for(Method method:methods){
				String methodName=method.getName();
				if(methodName.startsWith("get")){
					//过滤掉getClass方法
					if(methodName.equals("getClass")){
						continue;
					}
					Object fieldValue=method.invoke(bean);
					if(fieldValue!=null){
						map.put(methodName.toLowerCase().substring(3), fieldValue);
					}
				}
			}
		} catch (Exception e) {
			Log.e("Exception", ""+e);
		}
		
		return add(tableName,map);
	}
    
    /**
     * 关闭数据库
     */
    public void XClose(){
    	if(mDb != null){
    		mDb.close();
    	}
    }
}
